package yxk.report.wtc.wtte;

import com.google.common.collect.Maps;
import kd.bos.algo.*;
import kd.bos.algo.input.CollectionInput;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.entity.LocaleString;
import kd.bos.db.DB;
import kd.bos.db.DBRoute;
import kd.bos.entity.report.*;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.sdk.plugin.Plugin;
import kd.wtc.wtbs.common.util.SystemParamQueryUtil;
import kd.wtc.wtbs.common.util.WTCCollections;
import kd.wtc.wtte.business.attreport.AttReportService;
import org.jetbrains.annotations.NotNull;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 考勤数据查询表
 * 工时假勤云-考勤核算-考勤记录汇总
 * 报表取数赋值插件
 */
public class AttFilesDataReportListPlugin extends AbstractReportListDataPlugin implements Plugin {
    private SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd");
    protected Map<String, String> attItemMap;
    protected Map<String, Integer> attItemTypeMap;
    protected LinkedList<String> selectCol = new LinkedList();
    protected Map<String, String> sortColMap;

    protected List<Map<String,Object>> conn=new ArrayList<>();
    Set<String> settleInfos;
    private static final Log logger = LogFactory.getLog(AttFilesDataReportListPlugin.class);

    @Override
    public DataSet queryBatchBy(ReportQueryParam queryParam) {
        QFilter qFilter = attDayRecordDetailQFilters(queryParam,null);
        IReportBatchQueryInfo iReportBatchQueryInfo = queryParam.byBatchInfo();
        iReportBatchQueryInfo.setCountPerBatch(200);
        DataSet rows = QueryServiceHelper.queryDataSet(this.getClass().getName(), "wtdtd_attrecordbase", "personid", qFilter.toArray(), "personid asc");
        GroupbyDataSet groupSet = rows.groupBy(new String[]{"personid"});
        return groupSet.finish();
    }

    @Override
    public DataSet query(ReportQueryParam queryParam, Object o) throws Throwable {
         List<Row> currentBatchRows = queryParam.byBatchInfo().getCurrentBatchRows();
        if (WTCCollections.isEmpty(currentBatchRows)) {
            return Algo.create(this.getClass().getName()).createDataSetBuilder(new RowMeta(new Field[0])).build();
        } else {
            this.initQfilter(queryParam);
            this.getColumnGroupMap();
            this.selectCol.add("id");
            this.selectCol.add("personid");

            QFilter qFilter = attDayRecordDetailQFilters(queryParam, currentBatchRows);
            DataSet rows = QueryServiceHelper.queryDataSet(this.getClass().getName(), "wtdtd_attrecordbase", String.join(",", this.selectCol.toArray(new String[0])), qFilter.toArray(), "personid");
            //分组的人员档案ID
            Map<Long, Map<String, Object>> maps = new HashMap<>();
            Set<Long> personIds = new HashSet<>();
            //获取人员档案集合
            Set<Long> setLong = new HashSet<>();
            RowMeta createRowMeta = rows.getRowMeta();
            while (rows.hasNext()) {
                Row row = rows.next();
                Long id = row.getLong("id");
                Long personid = row.getLong("personid");
                setLong.add(id);
                personIds.add(personid);
                Map<String, Object> map = maps.get(personid);
                if (map == null || map.size() == 0) {
                    map = new HashMap<>();
                    for (String s : this.selectCol) {
                        if (!"id".equals(s)) {
                            map.put(s, row.get(s));
                        }
                    }
                    maps.put(personid, map);
                }
            }
            QFilter qf = new QFilter("attmain", QCP.in, setLong);
            Collection<Object[]> coll = new ArrayList<>();//创建显示行字段
            for (Long personId : personIds) {
                Map<String, Object> map = maps.get(personId);
                Field[] fields = createRowMeta.getFields();
                Object[] obj = new Object[fields.length];
                for (int i = 0; i < fields.length; i++) {
                    obj[i] = map.get(fields[i].getName());
                }
                coll.add(obj);
            }
            //获取考勤项目值
            DataSet dataSet = queryDetailById(qf);
            //获取考勤项目值
            DataSet attDataSet = querAttProjectValue(setLong);
            //groupby = groupby.count("fid");
            CollectionInput collectionInput = new CollectionInput(createRowMeta, coll);
            DataSet createDataSet = Algo.create(this.getClass().getName()).createDataSet(collectionInput);

            JoinDataSet oned = createDataSet.leftJoin(dataSet).on("personid", "attmain.personid");
            oned.select(this.selectCol.toArray(new String[0]), dataSet.getRowMeta().getFieldNames());
            DataSet finish = oned.finish();
            JoinDataSet on = finish.leftJoin(attDataSet).on("personid", "personid");
            on.select(finish.getRowMeta().getFieldNames(), attDataSet.getRowMeta().getFieldNames());
            return on.finish();
        }

    }

    private DataSet querAttProjectValue(Set<Long> ids){
        StringBuffer sql=new StringBuffer();
        sql.append("select ");
        sql.append(selectResultsStr());
        sql.append(" from f_fk_fattprojectvalue where ");
        sql.append("fattmain in(");
        String setIds = ids.toString();
        String setSub = setIds.substring(1, setIds.length() - 1);
        sql.append(setSub);
        sql.append(") GROUP BY fpersonid");
        DataSet rows = DB.queryDataSet(this.getClass().getName(), new DBRoute("wtc"), sql.toString());
        return rows;
    }

    /**
     * 考勤记录-明细项目信息 DataSer
     */
    private DataSet queryDetailById(@NotNull QFilter filters) {
        DataSet dataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), "wtdtd_attrecorddetail", this.selectStr(), filters.toArray(),null);
        GroupbyDataSet groupSet = dataSet.groupBy(this.getDetailGroupSelect());
        Iterator var4 = this.attItemMap.keySet().iterator();

        while(var4.hasNext()) {
            String item = (String)var4.next();
            groupSet.sum(item);
        }

        dataSet = groupSet.finish();
        return dataSet;
    }

    private String selectStr() {
        StringBuilder attItemStr = new StringBuilder();
        Iterator var2 = this.attItemMap.keySet().iterator();

        while(var2.hasNext()) {
            String item = (String)var2.next();
            attItemStr.append("case when ").append("attitemid").append(" = '").append(AttReportService.attIdDel(item)).append("'".toCharArray()).append(" then valuelong  end as ").append(item).append(" ,");
        }

        attItemStr.append(String.join(",", this.getDetailGroupSelect()));
        return attItemStr.toString();
    }

    private String selectResultsStr() {
        StringBuilder itemStr = new StringBuilder();
        itemStr.append("fpersonid as personid");
        for (Map<String, Object> map : this.conn) {
            itemStr.append(",");
            itemStr.append("MAX( case when ")
                    .append("ftime")
                    .append(" = '")
                    .append(map.get("time"))
                    .append("'  then " )
                    .append(map.get("sorttype"))
                    .append(" end )  as \"")
                    .append(map.get("number"))
                    .append("\"");
        }
        return itemStr.toString();
    }

    private String[] getDetailGroupSelect() {
        return new String[]{"attmain.personid"};
    }

    public static QFilter attDayRecordDetailQFilters(ReportQueryParam queryParam,List<Row> ids) {
        FilterInfo filter = queryParam.getFilter();

        DynamicObject conOrg = filter.getDynamicObject("con_org");//考勤管理组
        Date owndatestart = filter.getDate("owndatestart");//开始时间
        Date owndateend = filter.getDate("owndateend");//结束时间
        DynamicObjectCollection conAdminorg = filter.getDynamicObjectCollection("con_adminorg");//行政组织
        DynamicObjectCollection conAffiliateadminorg = filter.getDynamicObjectCollection("con_affiliateadminorg");//挂靠行政组织
        DynamicObjectCollection conEmpgroup = filter.getDynamicObjectCollection("con_empgroup");//考勤人员组
        DynamicObjectCollection attperinf = filter.getDynamicObjectCollection("attperinf");//人员
        QFilter qFilter=new QFilter("orgid", QCP.equals,conOrg.getPkValue());
        if(owndatestart != null && owndateend != null){
            qFilter.and("owndate",">=",owndatestart);
            qFilter.and("owndate","<=",owndateend);
        }

        if(conAdminorg != null){
            List<Long> orgIds=new ArrayList<>();
            for (int i = 0; i < conAdminorg.size(); i++) {
                DynamicObject org = conAdminorg.get(i);
                orgIds.add(Long.parseLong(org.getPkValue().toString()));
            }
            qFilter.and("attfilevid.adminorg", QCP.in,orgIds);
        }

        //挂靠行政组织
        if(conAffiliateadminorg != null){
            List<Long> adminOrgIds=new ArrayList<>();
            for (int i = 0; i < conAffiliateadminorg.size(); i++) {
                DynamicObject adOrg = conAffiliateadminorg.get(i);
                adminOrgIds.add(Long.parseLong(adOrg.getPkValue().toString()));
            }
            qFilter.and("attfilevid.affiliateadminorg", QCP.in,adminOrgIds);
        }
        if(conEmpgroup != null){
            List<Long> conIds=new ArrayList<>();
            for (int i = 0; i < conEmpgroup.size(); i++) {
                DynamicObject con = conEmpgroup.get(i);
                conIds.add(Long.parseLong(con.getPkValue().toString()));
            }
            qFilter.and("attfilevid.empgroup", QCP.in,conIds);
        }
        if(ids != null){
            List<Long>  personid=new ArrayList<>();
            for (Row row : ids) {
                Long id = row.getLong("personid");
                personid.add(id);
            }
            qFilter.and("personid", QCP.in,personid);
        }else
        if(attperinf != null){
            List<Long> perinIds=new ArrayList<>();
            for (int i = 0; i < attperinf.size(); i++) {
                DynamicObject single = attperinf.get(i);
                perinIds.add(single.getLong("attperson.id"));
            }
            qFilter.and("personid", QCP.in,perinIds);
        }

        return qFilter;
    }



    protected void initQfilter(ReportQueryParam queryParam) {
        Map<String, Map<String, String>> columnMap = getAttItemAndColumnMap(queryParam);
        this.attItemMap = (Map)columnMap.get("attiem");
        this.attItemTypeMap = queryAttItemTypeMap(this.attItemMap);
        this.selectCol = new LinkedList(((Map)columnMap.get("normal")).keySet());
        this.selectCol.addAll(((Map)columnMap.get("sort")).keySet());
        LinkedList<String> tempSelectCol = new LinkedList();
        this.settleInfos = new HashSet();
        this.selectCol.forEach((str) -> {
            if (str.startsWith("settleinfo")) {
                int index = str.indexOf(46);
                if (index >= 0) {
                    this.settleInfos.add(str.substring(index + 1));
                }
            } else {
                tempSelectCol.add(str);
            }

        });
        this.selectCol = tempSelectCol;
        this.sortColMap = (Map)columnMap.get("sorttype");
    }

    public static String attIdApp(long attItemId) {
        return attItemId + "_";
    }

    public static String attIdDel(String str) {
        return str.replace("_", "");
    }

    public static Map<String, Integer> queryAttItemTypeMap(Map<String, String> attitemMap) {
        Set<Long> keySet = (Set)attitemMap.keySet().stream().map((key) -> {
            return Long.valueOf(attIdDel(key));
        }).collect(Collectors.toSet());
        DynamicObjectCollection dCollection = QueryServiceHelper.query("wtbd_attitem", "id,number , dataaccuracy", new QFilter[]{new QFilter("id", "in", keySet)});
        Map<String, Integer> map = new HashMap(16);
        Iterator var4 = dCollection.iterator();

        while(var4.hasNext()) {
            DynamicObject dynamicObject = (DynamicObject)var4.next();
            map.put(attIdApp(dynamicObject.getLong("id")), dynamicObject.getInt("dataaccuracy"));
        }

        return map;
    }

    public static Map<String, Map<String, String>> getAttItemAndColumnMap(ReportQueryParam queryParam) {
        Map<String, Object> fieldMap = queryParam.getCustomParam();
        Map<String, String> attItemMap = Maps.newLinkedHashMapWithExpectedSize(16);
        Map<String, String> managingScopeMap = Maps.newLinkedHashMapWithExpectedSize(16);
        Map<String, String> depempJobMap = Maps.newLinkedHashMapWithExpectedSize(16);
        Map<String, String> wtteInfoMap = Maps.newLinkedHashMapWithExpectedSize(16);
        Map<String, String> columnMap = Maps.newLinkedHashMapWithExpectedSize(16);
        Map<String, String> sortMap = Maps.newLinkedHashMapWithExpectedSize(16);
        Map<String, String> sortTypeMap = Maps.newLinkedHashMapWithExpectedSize(16);
        Iterator var9 = fieldMap.entrySet().iterator();

        while(var9.hasNext()) {
            Map.Entry<String, Object> mapEntry = (Map.Entry)var9.next();
            Map<String, Object> map = (Map)mapEntry.getValue();
            String fieldSourceType = String.valueOf(map.get("fieldSourceType"));
            String number = String.valueOf(map.get("number"));
            String name = String.valueOf(map.get("name"));
            switch (fieldSourceType) {
                case "attiem":
                    attItemMap.put(number, name);
                    break;
                case "managingscope":
                    managingScopeMap.put(number, name);
                    break;
                case "depempjob":
                    depempJobMap.put(number, name);
                    break;
                case "wtteinfo":
                case "normal":
                    columnMap.put(number, name);
                    break;
                case "sort":
                    sortMap.put(number, name);
                    break;
                case "sorttype":
                    sortTypeMap.put(number, String.valueOf(map.get("sorttype")));
            }
        }

        Map<String, Map<String, String>> map = Maps.newHashMapWithExpectedSize(6);
        map.put("attiem", attItemMap);
        map.put("managingscope", managingScopeMap);
        map.put("depempjob", depempJobMap);
        map.put("wtteinfo", wtteInfoMap);
        map.put("normal", columnMap);
        map.put("sort", sortMap);
        map.put("sorttype", sortTypeMap);
        return map;
    }

    @Override
    public List<AbstractReportColumn> getColumns(List<AbstractReportColumn> columns) throws Throwable {
        List<AbstractReportColumn> reportColumns = super.getColumns(columns);
        this.columns(columns);
        Map<String,ReportColumnGroup> columnGroupMap=new HashMap<>();
        logger.info("getColumns.conn:{}",conn);
        if(conn != null && conn.size()>0){
            for (Map map : conn) {
                String time = String.valueOf(map.get("time"));
                ReportColumnGroup reportColumnGroup = columnGroupMap.get(time);
                if(reportColumnGroup == null){
                    reportColumnGroup=new ReportColumnGroup();
                    reportColumnGroup.setFieldKey(time);
                    Calendar cal=Calendar.getInstance();
                    cal.setTimeInMillis(Long.parseLong(time));
                    String formatted = format.format(cal.getTime());
                    reportColumnGroup.setCaption(new LocaleString(formatted));
                }
                String number = String.valueOf(map.get("number"));
                String fieldType = String.valueOf(map.get("fieldtype"));
                boolean isHyperlink = Boolean.parseBoolean(String.valueOf(map.get("ishyperlink")));
                boolean freeze = Boolean.parseBoolean(String.valueOf(map.get("freeze")));
                boolean isHide = Boolean.parseBoolean(String.valueOf(map.get("isHide")));
                String name = String.valueOf(map.get("name"));
                ReportColumn rptColumn = this.createRptColumn(new LocaleString(name), number, fieldType, isHyperlink, this.attItemTypeMap);
                rptColumn.setFreeze(freeze);
                rptColumn.setHide(isHide);
                reportColumnGroup.getChildren().add(rptColumn);
                columnGroupMap.put(time,reportColumnGroup);
            }

        }
        columnGroupMap.keySet();
        List<String> collect = columnGroupMap.keySet().stream()
                .sorted().collect(Collectors.toList());
        for (String s : collect) {
            reportColumns.add(columnGroupMap.get(s));
        }
        return reportColumns;
    }

    protected  void getColumnGroupMap(){
        ReportQueryParam queryParam = this.getQueryParam();
        if(queryParam != null){
            LinkedHashMap<String, Object> displayMap = (LinkedHashMap)queryParam.getCustomParam();
            Iterator var3 = displayMap.entrySet().iterator();
            while (var3.hasNext()){
                Map.Entry<String, Object> mapEntry = (Map.Entry)var3.next();
                Map<String, Object> map = (Map)mapEntry.getValue();
                if("custom".equals(map.get("fieldSourceType"))){
                    conn.add(map);
                }
            }
        }
    }
    protected void columns(List<AbstractReportColumn> reportColumns) {
        LinkedHashMap<String, Object> displayMap = (LinkedHashMap)this.getQueryParam().getCustomParam();
        reportColumns.clear();
        Iterator var3 = displayMap.entrySet().iterator();
        List<Map<String, Object>> list=new ArrayList<>();
        while(var3.hasNext()) {
            Map.Entry<String, Object> mapEntry = (Map.Entry)var3.next();
            Map<String, Object> map = (Map)mapEntry.getValue();
            if("custom".equals(map.get("fieldSourceType"))){

            }else
            if (!"sorttype".equals(map.get("fieldSourceType"))) {
                String key = String.valueOf(map.get("number"));
                String fieldType = String.valueOf(map.get("fieldtype"));
                boolean isHyperlink = Boolean.parseBoolean(String.valueOf(map.get("ishyperlink")));
                boolean freeze = Boolean.parseBoolean(String.valueOf(map.get("freeze")));
                boolean isHide = Boolean.parseBoolean(String.valueOf(map.get("isHide")));
                String fieldSourceType = String.valueOf(map.get("fieldSourceType"));
                if ("attmain.personid.name".equals(key)) {
                    this.genAttPersonNameColumns(reportColumns, map, key, fieldType, freeze, isHide);
                } else {
                    String name = String.valueOf(map.get("name"));
                    String number = String.valueOf(map.get("number"));
                    ReportColumn column;
                    if ("attiem".equals(fieldSourceType)) {
                        column = this.createRptColumn(new LocaleString(name), number, fieldType, false, this.attItemTypeMap);
                    } else {
                        column = this.createRptColumn(new LocaleString(String.valueOf(map.get("name"))), key, fieldType, false, this.attItemTypeMap);
                    }

                    column.setFreeze(freeze);
                    column.setHide(isHide);
                    reportColumns.add(column);
                }
            }
        }
    }

    private void genAttPersonNameColumns(List<AbstractReportColumn> reportColumns, Map<String, Object> map, String key, String fieldType, boolean freeze, boolean isHide) {
        ReportColumnGroup reportColumnGroup = null;
        if (!reportColumns.isEmpty() && reportColumns.get(0) instanceof ReportColumnGroup) {
            reportColumnGroup = (ReportColumnGroup)reportColumns.get(0);
        }

        if (reportColumnGroup == null) {
            ReportColumn column = this.createRptColumn(new LocaleString(String.valueOf(map.get("name"))), key, fieldType, true, this.attItemTypeMap);
            column.setFreeze(freeze);
            column.setHide(isHide);
            reportColumns.add(column);
        } else {
            List<AbstractReportColumn> children = reportColumnGroup.getChildren();
            if (Boolean.FALSE.equals(SystemParamQueryUtil.isFrozenOpen())) {
                children.remove(1);
            } else {
                ((ReportColumn)children.get(1)).setFreeze(freeze);
            }

            ReportColumn reportColumn = (ReportColumn)children.get(0);
            reportColumn.setHyperlink(true);
            reportColumn.setFreeze(freeze);
            reportColumn.setCaption(new LocaleString(String.valueOf(map.get("name"))));
            reportColumns.add(reportColumnGroup);
        }

    }

    /**
     *
     * @param caption       --设置报表列名称
     * @param fieldVal      --设置列标识
     * @param fieldType     --设置字段类型
     * @param isHyperlink   --设置是否显示为超链接
     * @param typeMap       --设置小数精度
     * @return
     */
    public ReportColumn createRptColumn(LocaleString caption, String fieldVal, String fieldType, boolean isHyperlink, Map<String, Integer> typeMap) {
        ReportColumn reportColumn = new ReportColumn();
        ColumnStyle style = new ColumnStyle();
        style.setTextAlign("center");
        reportColumn.setStyle(style);//样式设置
        reportColumn.setCaption(caption);
        reportColumn.setFieldKey(fieldVal);
        switch (fieldType) {
            case "amount":
                reportColumn.setFieldType("amount");//--设置字段类型
                reportColumn.setZeroShow(true);     //--设置为零显示
                break;
            case "decimal":
                reportColumn.setFieldType("decimal");
                reportColumn.setZeroShow(true);
                if (typeMap.get(fieldVal) != null) {
                    reportColumn.setScale((Integer)typeMap.get(fieldVal));  //--设置小数精度
                }else{
                    reportColumn.setScale(2);
                }
                break;
            case "integer":
                reportColumn.setFieldType("integer");
                reportColumn.setZeroShow(true);
                break;
            case "date":
                reportColumn.setFieldType("date");
                if ("calculatedate".equals(fieldVal)) {
                    reportColumn.setFieldType("text");
                }
                break;
            case "checkbox":
                reportColumn.setFieldType("checkbox");
                break;
            default:
                reportColumn.setFieldType("text");
        }

        reportColumn.setHideSingleColumnRow(false);
        reportColumn.setWidth(new LocaleString("200px"));
        reportColumn.setHyperlink(isHyperlink);
        return reportColumn;
    }

}